package com.ellecity06.common.widgets

import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.LinearGradient
import android.graphics.Paint
import android.graphics.Shader
import android.graphics.Typeface
import android.util.AttributeSet
import android.view.View
import android.view.animation.DecelerateInterpolator
import com.ellecity06.common.R
import com.ellecity06.common.ktx.colorResToColorId
import com.ellecity06.common.ktx.dimenResToInt
import com.ellecity06.common.ktx.sp2px
import com.ellecity06.common.utils.logD

class ExperienceBar
@JvmOverloads
constructor(context: Context,
            attrs: AttributeSet? = null,
            defStyleAttr: Int = 0,
            defStyleRes: Int = 0)
    : View(context, attrs, defStyleAttr, defStyleRes) {

    //整个View的宽度
    private var mViewWidth = 0F

    //整个View的高度
    private var mViewHeight = 0F

    //内部经验条的宽度
    private var mLineWidth = 0F

    //内部经验条的高度
    private var mLineHeight = 0F

    //内部经验条的左边距
    private var mLineLeft = 0F

    //内部经验条的上边距
    private var mLineTop = 0F

    //经验条的圆角
    private var mRadius = 0F

    //等级圆点的间隔
    private var mPointInterval = 0F

    //当前经验值
    private var mExperience = 0.00

    //每一等级占总长的百分比
    private var mLevelPercent = 1F

    //经验条百分比（相对于总进度）
    private var mExperiencePercent = 0F

    //当前等级
    private var mCurrentLevel = 0

    //升级所需要的经验列表
    private val mLevelList = mutableListOf<Int>()
    private val orgList = mutableListOf<Int>()

    //各种颜色值
    // 进度级别圆圈颜色
    private val mPointColor = Color.parseColor("#F0DDFF")

    //
    private val mLineColor = Color.parseColor("#F0DDFF")
    private val mShaderStartColor = R.color.textColorAccent.colorResToColorId()
    private val mShaderEndColor = R.color.textColorAccent.colorResToColorId()
    private val mStrokeColor = Color.parseColor("#000000")

    //文字
    private val textPaint by lazy {
        Paint().apply {
            color = Color.parseColor("#8D15C9")
            textSize = 10F.sp2px().toFloat()
            typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
        }
    }

    //各种画笔
    private val mStrokePaint by lazy {
        Paint().apply {
            color = mStrokeColor
        }
    }
    private val mShaderPaint by lazy {
        Paint().apply {
            color = mShaderStartColor
        }
    }
    private val mLinePaint by lazy {
        Paint().apply {
            color = mLineColor
        }
    }
    private val mLevelAchievedPaint by lazy {
        Paint().apply {
            color = mShaderEndColor
        }
    }
    private val mLevelNotAchievedPaint by lazy {
        Paint().apply {
            color = mPointColor
        }
    }
    //各种画笔

    fun updateExperience(experience: Double) {
        if (mLevelList.isEmpty() || experience == mExperience) return
        mExperience = experience
        startAnimator(mExperiencePercent, computerLevelInfo())
    }

    /**
     * 外界设置等级信息
     */
    fun setLevelInfo(experience: Double, list: List<Int>) {
        mExperience = experience
        mLevelList.clear()
        mLevelList.addAll(list)
        orgList.clear()
        orgList.addAll(list)
        computerPointInterval()
        startAnimator(0F, computerLevelInfo())
    }

    //动画相关
    private var mAnimator: ValueAnimator? = null

    //动画时长
    private val mAnimatorDuration = 500L

    //插值器
    private val mInterpolator by lazy { DecelerateInterpolator() }

    //动画值回调
    private val mAnimatorListener by lazy {
        ValueAnimator.AnimatorUpdateListener {
            mExperiencePercent = it.animatedValue as Float
            invalidate()
        }
    }

    /**
     * 开始经验条动画
     */
    private fun startAnimator(start: Float, end: Float) {
        mAnimator?.cancel()
        mAnimator = ValueAnimator.ofFloat(start, end).apply {
            duration = mAnimatorDuration
            interpolator = mInterpolator
            addUpdateListener(mAnimatorListener)
            start()
        }
    }
    //动画相关

    /**
     * 根据等级信息，计算出要绘制的经验条相关参数,并将最终的进度条比例返回
     */
    private fun computerLevelInfo(): Float {
        if (mLevelList.isNotEmpty()) {
            mCurrentLevel = 0
            for (value in mLevelList) {
                if (mExperience >= value) mCurrentLevel++
                else break
            }
            if (mCurrentLevel < mLevelList.size) {
                mLevelPercent = 1F / mLevelList.size
                val lastLevelExperience = if (mCurrentLevel > 0) mLevelList[mCurrentLevel - 1] else 0
                val currentLevelPercent = (mExperience - lastLevelExperience) /
                        (mLevelList[mCurrentLevel] - lastLevelExperience).toFloat()
                return ((mCurrentLevel + currentLevelPercent) * mLevelPercent).toFloat()
            }
        }
        return 1F
    }

    /**
     * 计算各个等级点之间的间隔
     */
    private fun computerPointInterval() {
        if (mLineWidth > 0F || mLevelList.isNotEmpty()) {
            mPointInterval = mLineWidth / mLevelList.size
        }
    }

    /**
     * 测量各种尺寸
     */
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        val width = MeasureSpec.getSize(widthMeasureSpec)
        mViewWidth = (width - paddingStart - paddingEnd).toFloat()
        val height = R.dimen.dp_48.dimenResToInt() + paddingTop + paddingBottom
        mViewHeight = R.dimen.dp_48.dimenResToInt().toFloat()
        mRadius = mViewHeight

        mLineHeight = R.dimen.dp_18.dimenResToInt().toFloat()
        mLineTop = R.dimen.dp_8.dimenResToInt().toFloat()

        mLineWidth = mViewWidth - mLineTop * 2
        mLineLeft = mLineTop
        setShaderColor()
        computerPointInterval()
        logD("height=${height},,mViewHeight=${mViewHeight},,mRadius${mRadius},,mLineHeight=${mLineHeight},,mLineTop=${mLineTop},,mLineWidth=${mLineWidth},,")
        setMeasuredDimension(width, height.toInt())
    }

    /**
     * 设置经验条的渐变色
     */
    private fun setShaderColor() {
        mShaderPaint.shader = LinearGradient(0F, 0F, mLineWidth, 0F,
                mShaderStartColor, mShaderEndColor, Shader.TileMode.CLAMP)
    }

    /**
     * 绘制View
     */
    override fun onDraw(canvas: Canvas) {
        canvas.save()
        canvas.translate(paddingStart.toFloat(), paddingTop.toFloat())
//        drawBackground(canvas)
        drawExperienceBar(canvas)
        drawLevelPoint(canvas)
        drawText(canvas)
        canvas.restore()
    }


    /**
     * 绘制背景边框
     */
    private fun drawBackground(canvas: Canvas) {
        canvas.drawRoundRect(0F, 0F, mViewWidth, mViewHeight, mRadius, mRadius, mStrokePaint)
    }

    /**
     * 绘制经验条
     */
    private fun drawExperienceBar(canvas: Canvas) {
        val save = canvas.saveCount
        canvas.save()
        canvas.translate(mLineLeft, mLineTop)
        logD("mLineHeight==${mLineHeight},,mExperiencePercent=$mExperiencePercent，，，w=${mLineWidth * mExperiencePercent}")
        //绘制经验条底部背景
        canvas.drawRoundRect((mLineWidth * mExperiencePercent - mLineHeight).coerceAtLeast(0F),
                0F, mLineWidth, mLineHeight, mRadius, mRadius, mLinePaint)
        //绘制渐变的经验条
        if (mExperiencePercent >0.02) {
            canvas.drawRoundRect(0F, 0F, mLineWidth * mExperiencePercent, mLineHeight,
                mRadius, mRadius, mShaderPaint)
        }else {
            canvas.drawArc(0F, mLineHeight/3, mLineWidth * mExperiencePercent, mLineHeight-mLineHeight/3, 90f, 180F, true, mShaderPaint);
//            canvas.drawRoundRect(0F, mLineHeight/3, mLineWidth * mExperiencePercent, mLineHeight-mLineHeight/3,
//                mRadius, mRadius, mShaderPaint)
        }


        canvas.restoreToCount(save)
    }

    private fun drawText(canvas: Canvas) {
        if (orgList.isNotEmpty()) {


            val measureText = textPaint.measureText("￥${mExperience}")
            if (mExperiencePercent >0.1) {

                canvas.drawText("￥${mExperience}", mLineWidth * mExperiencePercent - measureText / 2, mViewHeight - mLineHeight + mLineTop + R.dimen.dp_5.dimenResToInt(), textPaint)
            } else {
                canvas.drawText("￥${mExperience}", mLineLeft, mViewHeight - mLineHeight + mLineTop + R.dimen.dp_5.dimenResToInt(), textPaint)
            }
//            if (mExperience <=5000) {
//                val measureText2 = textPaint.measureText("￥${orgList[orgList.size - 1]}")
//                canvas.drawText("￥${orgList[orgList.size - 1]}", mLineWidth - measureText2, mViewHeight - mLineHeight + mLineTop + R.dimen.dp_5.dimenResToInt(), textPaint)
//            }


        }
    }

    /**
     * 绘制等级分割点
     */
    private fun drawLevelPoint(canvas: Canvas) {
        if (mLevelList.size > 1) {
            val save = canvas.saveCount
            canvas.save()
            canvas.translate(mLineLeft, 0F)

            //等级圆点的圆心Y轴坐标(由于经验条是水平的，所以所有Y轴坐标都一样)
            val cy = mLineHeight
            //总共有n - 1个等级圆点，所以从1开始画，以达成的等级大圆点，未达成就是小圆点
            for (level in 1 until mLevelList.size + 1) {


                val achieved = mExperience >= mLevelList[level - 1]
                canvas.drawCircle(mPointInterval * level, cy,
                        if (achieved) mLineHeight * 2 / 3 else mLineHeight * 2 / 3,
                        if (achieved) mLevelAchievedPaint else mLevelNotAchievedPaint)
            }

            canvas.restoreToCount(save)
        }
    }

}